package server_service

/**
* @author aFun
* @data 2025/4/11 19:21
* @email: afunaaa222@163.com / 1030935903
* @address: Guangdong University of Technology, China
 */

import (
	"camp_lucky_draw/entity"
	"camp_lucky_draw/server"
	"camp_lucky_draw/transfer"
	"encoding/json"
	"fmt"
	"github.com/garyburd/redigo/redis"
	"github.com/streadway/amqp"
	"net"
	"strconv"
)

type CheckFunc func(role *entity.Role, Args map[string]interface{}) error

type UserProcess struct {
	Conn net.Conn
}

func (this *UserProcess) Enter_world(mes *entity.Msg) (err error) {
	Id, _ := strconv.Atoi(mes.Request_data)
	role := &entity.Role{}
	role.ID = uint(Id)
	resMes := &entity.Msg{}
	if err := server.DB.Preload("Lucky_draw").Find(&role, "id = ?", Id).Error; err != nil {
		resMes = &entity.Msg{
			Code:    mes.Code,
			Status:  false,
			Message: err.Error(),
		}
	} else {
		// 存储Role数据
		server.OnlineUserMgr.Mutex.Lock()
		server.OnlineUserMgr.OnlineUsers[this.Conn] = role
		server.OnlineUserMgr.OnlineIdConn[role.ID] = this.Conn
		server.OnlineUserMgr.Mutex.Unlock()
		respData, err := json.Marshal(role)
		if err != nil {
			return err
		}
		resMes = &entity.Msg{
			Code:          mes.Code,
			Status:        true,
			Repsonse_data: string(respData),
		}
	}
	return this.Send_response(resMes)
}

func (this *UserProcess) Self_lucky_draw_data(mes *entity.Msg) (err error) {
	Id, _ := strconv.Atoi(mes.Request_data)
	LuckDraw := &entity.LuckyDraw{}
	resMes := &entity.Msg{}
	if err := server.DB.Find(&LuckDraw, "role_id = ?", Id).Error; err != nil {
		resMes = &entity.Msg{
			Code:    mes.Code,
			Status:  false,
			Message: err.Error(),
		}
	} else {
		respData, err := json.Marshal(LuckDraw)
		if err != nil {
			return err
		}
		resMes = &entity.Msg{
			Code:          mes.Code,
			Status:        true,
			Repsonse_data: string(respData),
		}
	}
	fmt.Println(LuckDraw)

	return this.Send_response(resMes)
}

func (this *UserProcess) Floor_lucky_draw_data(mes *entity.Msg) error {
	redisConn := server.RedisPool.Get()
	defer redisConn.Close()

	// 从redis中读取
	cacheKey := "floor_rewards_cache"
	cached, err := redis.Bytes(redisConn.Do("GET", cacheKey))
	if err == nil && len(cached) > 0 {
		resMes := &entity.Msg{
			Code:          mes.Code,
			Status:        true,
			Repsonse_data: string(cached),
		}
		fmt.Println("数据从redis读取...")
		return this.Send_response(resMes)
	}

	// 不在redis的话则从配置中读取，然后存入redis
	FloorRewards := server.CampLuckyDrawData["floor_rewards"].([]interface{})
	var RespFloorRewardsLst []entity.Client_floor_reward
	for _, v := range FloorRewards {
		data := v.(map[string]interface{})
		var maxQuantity int64 = -1
		if data["maxQuantity"] != nil {
			maxQuantity = int64(data["maxQuantity"].(float64))
		}
		fr := entity.Client_floor_reward{
			Floor:       int8(data["floor"].(float64)),
			Pos:         int8(data["pos"].(float64)),
			ItemName:    data["itemName"].(string),
			Quantity:    int64(data["quantity"].(float64)),
			MaxQuantity: maxQuantity,
		}
		RespFloorRewardsLst = append(RespFloorRewardsLst, fr)
	}
	respData, err := json.Marshal(RespFloorRewardsLst)
	if err != nil {
		return err
	}

	fmt.Println("设置redis数据....")
	_, _ = redisConn.Do("SET", cacheKey, string(respData), "EX", 200) // 600 = 10min！

	resMes := &entity.Msg{
		Code:          mes.Code,
		Status:        true,
		Repsonse_data: string(respData),
	}
	return this.Send_response(resMes)
}

func (this *UserProcess) Cumulative_lucky_draw_data(mes *entity.Msg) error {
	redisConn := server.RedisPool.Get()
	defer redisConn.Close()

	// 从redis中读取
	cacheKey := "cumulative_rewards_cache"
	cached, err := redis.Bytes(redisConn.Do("GET", cacheKey))
	if err == nil && len(cached) > 0 {
		resMes := &entity.Msg{
			Code:          mes.Code,
			Status:        true,
			Repsonse_data: string(cached),
		}
		fmt.Println("数据从redis读取...")
		return this.Send_response(resMes)
	}

	CumulativeRewards := server.CampLuckyDrawData["cumulative_rewards"].([]interface{})
	var RespCumulativeRewardsLst []entity.Client_cumulative_reward
	for _, v := range CumulativeRewards {
		data := v.(map[string]interface{})
		var quantity int64 = -1
		if data["quantity"] != nil {
			quantity = int64(data["quantity"].(float64))
		}
		cr := entity.Client_cumulative_reward{
			TokenCost: int64(data["tokenCost"].(float64)),
			ItemName:  data["itemName"].(string),
			Quantity:  quantity,
		}
		RespCumulativeRewardsLst = append(RespCumulativeRewardsLst, cr)
	}
	respData, err := json.Marshal(RespCumulativeRewardsLst)
	if err != nil {
		return err
	}
	resMes := &entity.Msg{
		Code:          mes.Code,
		Status:        true,
		Repsonse_data: string(respData),
	}

	fmt.Println("设置redis数据....")
	_, _ = redisConn.Do("SET", cacheKey, string(respData), "EX", 200)

	return this.Send_response(resMes)
}

func (this *UserProcess) Draw(mes *entity.Msg) (err error) {
	IsProtected, _ := strconv.ParseBool(mes.Request_data)
	Args := make(map[string]interface{})
	Args["is_protected"] = IsProtected
	resMes := &entity.Msg{}
	CurRole := server.OnlineUserMgr.OnlineUsers[this.Conn]
	if err := Do_draw(CurRole, Args); err != nil {
		resMes = &entity.Msg{
			Code:    mes.Code,
			Status:  true, // 理论上这里应该是false,但是其实网络请求是成功了的，是客户非法操作导致，QPS等指标不应认为是服务器问题的
			Message: err.Error(),
		}
	} else {
		resMes = &entity.Msg{
			Code:   mes.Code,
			Status: true,
		}

		// 送进消息队列 做排行榜的异步更新
		MQMes := entity.LuckyDrawRank{
			Role_id:         CurRole.ID,
			Consumed_tokens: CurRole.Lucky_draw.Consumed_tokens,
			Draw_num:        CurRole.Lucky_draw.Draw_num,
		}
		body, _ := json.Marshal(MQMes)
		err := RankingPublish("ranking_update", body)
		if err != nil {
			fmt.Println("排行榜MQ发送消息异常:", err)
		}
	}
	return this.Send_response(resMes)
}

func (this *UserProcess) Gain_floor_rewards(mes *entity.Msg) (err error) {
	fr := &entity.Client_floor_reward{}
	err = json.Unmarshal([]byte(mes.Request_data), &fr)
	if err != nil {
		return err
	}
	Args := make(map[string]interface{})
	Args["floor"] = fr.Floor
	Args["pos"] = fr.Pos
	resMes := &entity.Msg{}
	if err = Do_get_floor_rewards(server.OnlineUserMgr.OnlineUsers[this.Conn], Args); err != nil {
		resMes = &entity.Msg{
			Code:    mes.Code,
			Status:  true, // 理论上这里应该是false,但是其实网络请求是成功了的，是客户非法操作导致，QPS等指标不应认为是服务器问题的
			Message: err.Error(),
		}
	} else {
		resMes = &entity.Msg{
			Code:   mes.Code,
			Status: true,
		}
	}
	return this.Send_response(resMes)
}

func (this *UserProcess) Gain_cumulative_rewards(mes *entity.Msg) (err error) {
	var indexes []int64
	err = json.Unmarshal([]byte(mes.Request_data), &indexes)
	if err != nil {
		return err
	}
	Args := make(map[string]interface{})
	Args["Index"] = indexes
	resMes := &entity.Msg{}
	if err = Do_get_cumulative_rewards(server.OnlineUserMgr.OnlineUsers[this.Conn], Args); err != nil {
		resMes = &entity.Msg{
			Code:    mes.Code,
			Status:  true, // 理论上这里应该是false,但是其实网络请求是成功了的，是客户非法操作导致，QPS等指标不应认为是服务器问题的
			Message: err.Error(),
		}
	} else {
		resMes = &entity.Msg{
			Code:   mes.Code,
			Status: true,
		}
	}
	return this.Send_response(resMes)
}

func (this *UserProcess) Disconnect(mes *entity.Msg) (err error) {
	resMes := &entity.Msg{
		Code:   mes.Code,
		Status: true,
	}
	this.Send_response(resMes)
	roleId := server.OnlineUserMgr.OnlineUsers[this.Conn].ID
	server.OnlineUserMgr.Mutex.Lock()
	delete(server.OnlineUserMgr.OnlineUsers, this.Conn)
	delete(server.OnlineUserMgr.OnlineIdConn, roleId)
	server.OnlineUserMgr.Mutex.Unlock()
	return nil
}

// ====================================================函数封装相关=========================================================================
func (this *UserProcess) Send_response(resMes *entity.Msg) (err error) {
	data, err := json.Marshal(resMes)
	if err != nil {
		return err
	}
	tf := &transfer.Transfer{
		Conn: this.Conn,
	}
	err = tf.WritePkg(data)
	if err != nil {
		return err
	}
	return nil
}

func RankingPublish(queue string, body []byte) error {
	ch, err := server.MQ.Channel()
	if err != nil {
		return err
	}
	defer ch.Close()

	_, err = ch.QueueDeclare(
		queue, true, false, false, false, nil,
	)
	if err != nil {
		return err
	}

	return ch.Publish(
		"", queue, false, false,
		amqp.Publishing{
			ContentType: "application/json",
			Body:        body,
		},
	)
}
